package com.lzj.framework.security;

import com.lzj.common.core.service.PermissionService;
import com.lzj.common.enums.HttpMethod;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 自定义认证 - 授权管理器
 * 用于实现基于路径的动态权限过滤
 *
 * @author 贱贱
 */
@Component
public class DynamicUrlAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
    
    @Resource
    private PermissionService permissionService;

    /**
     * AuthenticatedAuthorizationManager springSecurity提供的认证管理器
     */
    private final AuthenticatedAuthorizationManager<RequestAuthorizationContext> authenticatedAuthorizationManager = new AuthenticatedAuthorizationManager<>();;
    

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
        
        // 未登录不允许访问
        authenticatedAuthorizationManager.verify(authentication,context);
        
        // 请求对象
        HttpServletRequest request = context.getRequest();
        // 全部权限配置
        List<AntPathRequestMatcher> allPermission = permissionService.getAllPermission().stream()
            .map(this::permsToMatch)
            .collect(Collectors.toList());
        // 登录用户权限集合
        List<AntPathRequestMatcher> authorities = authentication.get().getAuthorities().stream()
            .map(authority -> this.permsToMatch(authority.getAuthority().trim()))
            .collect(Collectors.toList());


        if (
            // OPTIONS不过滤
            HttpMethod.OPTIONS.matches(request.getMethod())
            // 没有该请求路径的权限设置
            || allPermission.stream().noneMatch(matcher -> matcher.matcher(request).isMatch())
        ) return new AuthorizationDecision(true);

        // 权限判断
        boolean isGranted = authorities.stream().anyMatch(matcher -> matcher.matcher(request).isMatch());

        return new AuthorizationDecision(isGranted);
    }

    /**
     * 登录了吗?
     * @param authentication 认证对象
     * @return 是否
     */
    private boolean isLogin(Authentication authentication) {
        return authentication != null && isNotAnonymous(authentication) && authentication.isAuthenticated();
    }

    /**
     * 是否不是匿名用户
     * @param authentication 认证信息
     * @return 是否
     */
    private boolean isNotAnonymous(Authentication authentication) {
        return !new AuthenticationTrustResolverImpl().isAnonymous(authentication);
    }

    /**
     * 权限字符转matcher
     * @param perms 权限字符
     * @return AntPathRequestMatcher
     */
    private AntPathRequestMatcher permsToMatch(String perms) {
        String[] pattern = perms.split(":");
        AntPathRequestMatcher matcher;
        if (pattern.length == 1) {
            matcher = new AntPathRequestMatcher(pattern[0]);
        } else {
            matcher = new AntPathRequestMatcher(pattern[1], HttpMethod.resolve(pattern[0]).name());
        }
        return matcher;
    }
    
    
}
